Performance

Performance is something we discuss a lot. We want to make sure that our applications are fast and responsive. According to the grape-vine, if our app doesn't load in a few seconds, users will leave.

Heck, we even created our own holy grail:

Every app must load in under 100ms, never fall below 60fps, and feel buttery smooth. Also it must respons to every user interaction in under 50ms.

And to be honest, that is whole well possible. It requires paying attention to detail. It requires measuring and optimizing. I brought this to quite a few teams and they were able to achieve it. It is not easy, but it is possible. And it is worth it. Because if we can achieve that, we can create amazing user experiences. We can create apps that are fast and responsive. We can create apps that users love to use.

But first things first

The above is a great goal to strive for, but before we can even think about optimizing for performance, we need to make sure that our app is actually working. We need to make sure that it is functional and that it meets the requirements of our users. Honestly, a lot off apps out there forgot about that part. They are so focused on performance that they forget about the user experience. They forget about the fact that users want to be able to use their app and that they want to be able to do what they need to do.

Then there is the fact that performance can mean very different things to different people. And even it can be different for different apps. For most apps, the most important performance metric seems to be "developer velocity". How fast can we ship features? How fast can we fix bugs? How fast can we iterate? And that is a very valid metric. If we can't ship features, if we can't fix bugs, if we can't iterate, then our app is not going to be successful. Turns out, if you put the whip to your developers, they will start cutting corners. In most cases those corners are very costly, especially in the context of our "holy grail".

Then there is the next thing. The "holy grail" is aimed at public facing apps that are trying to sell something. The app we are working on might be very different. Should we just forego performance in that case? No, of course not. But we should be realistic about our goals. We should be realistic about what we can achieve and what we should achieve. We should focus on the things that matter and not get distracted by the things that don't matter.

You must have a performance talk in with your team and include all stakeholders in this discussion. Make sure you start of identifying what performance means for your app. Make a list goals and non-goals. Then set up tooling that measure those goals, and make sure you don't merge anything that doesn't meet those. And when it turns out you can't meet the goals, inform all stakeholders, and adjust the goals.

Also, short and long term performance goals can be different. However, when your short term goal is "optimize velocity", be aware that "fixing" performance is going to be a lot more expensive. And that is not just because of the technical debt you are creating, but also because of the fact that you are creating a culture of cutting corners. And that is going to be very hard to change. So be careful with that.

As with all things in life, it is about finding balance. Easy to write, hard to do.

What kinds of performance are there?

The list is endless, but I'm going to list a few common ones:

For all of those, there is a very simple rule: Less is more. There is a common trait here. Most of those will adhere to: 'ship less JS'. Moderation is key, especially when it comes to JS.

that feels arbitrary

Yeah, it is. Also, it is only focusing on the frontend part of you app. We tend to forget that the frontend is not the whole story. The backend is even more important. When your API calls take 5 seconds, there is nothing you can do in your frontend to make your app fast. You can only manage the perceived performance so far. So, make sure that yyour backend is includes in your goals and that you are measuring it as well. Realize that scalability is also a performance metric. And that that is so much more depending on your backend than on your frontend. So, make sure you are paying attention to that as well.

here is a small overview of things you should monitor for your backend:

Again, less is more. Even on "serverless" architectures those numbers matter. Perhaps even more, because you are paying for them. So, make sure you are monitoring those as well and that you are optimizing for them as well.

Do you have more data?

Sure, I have heaps of data. Which brings me to the performance of data. Yes, there are performance metrics for data as well. I'm not even talking about the API timings. list time:

Again, less is more. This is even more off a balancing act as the other kind of performances. Requesting all data is the easiest way to make sure your app is fast. But it is also the easiest way to make sure your app is slow. Huh? Well, while building the app, you test data-set will probably have a couple of hundred rows. Requesting all data is is fast, because you only have to do 1 request. But once you hit 100K rows problems start appearing. Firstly, client memory will fill up, making your app slower. Secondly, parsing this amount of data will take its toll. Not to forget about the fact all this data needs to be send to the client to begin with.

Requesting all data upfront is a antipatten that is very common. It often stems fro the so called smart/dumb component pattern. The smart component is responsible for fetching all data and then passing it down to the dumb components. This is a very common pattern, but it can lead to performance problems. So, be careful with that.

ProTip: Only load the data you need for the component at hand. If you need to show a list of items, just fetch the ID's for the list. The backend can take care of sorting and filtering. You can then iterate over the list, and hand the ID's to the child components, which can then fetch the data they need. This way you are only fetching the data you need, and you are not fetching data that you don't need.

Bonus tip: Don't worry about the number of api calls. If this becomes a problem, you can put in a cache, or batching layer. This should not be a concern of the component itself. The component should just be able to fetch the data it needs, and not worry about how that data is fetched.

On the other hand, when you are fetching a list of id's and then fetching each item separately, you are making way more API calls. There are ways to mitigate this, but again, its a balancing act. For some use cases it might be worth it to fetch all data upfront (this is more unlikely than you think, but it can happen). For most use cases, it is not worth it. So, make sure you are paying attention to this as well. Also, most backends do have a way to do batch requests. So, you can put in a data-layer that takes care of batching and caching for you. This way, you can fetch the data you need, without worrying about the number of API calls you are making.

Note that I'm mostly talking about fetching rows of data. I'm not ignoring limiting the ammount of columns